package com.blog.controller;
import com.blog.Utils.*;
import com.blog.annotion.LoginAnnotatio;
import com.blog.base.Constans;
import com.blog.base.ThreadLocalUserId;
import com.blog.bean.domain.User;
import com.blog.bean.dto.PassDTO;
import com.blog.bean.dto.UserDTO;
import com.blog.exception.ServiceException;
import com.blog.service.AttentionService;
import com.blog.service.LikeService;
import com.blog.service.UserService;
import com.blog.bean.vo.LoginVo;
import com.blog.bean.vo.UserErrorVO;
import com.blog.bean.vo.UserVO;
import com.google.code.kaptcha.Producer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;

/**
 * @author 任浩
 * @version 1.0
 */

@Slf4j
@RequestMapping("/user")
@RestController
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private Producer kaptchaProducer;
    @Autowired
    private SensitiveWordUtils sensitiveWordUtils;
    @Autowired
    private LikeService likeService;
    @Autowired
    private AttentionService attentionService;
    @Autowired
    private ThreadLocalUtil threadLocalUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 新加用户
     * @param userDTO
     * @return
     */
    @PostMapping
    public Result checkUser(@RequestBody UserDTO userDTO){
        //进行检验账户是否申请成功。
       UserErrorVO userErrorVO = userService.check(userDTO);

       return Result.success(userErrorVO);
    }

    /**
     * 激活用户
     * @param id
     * @return
     */
    @GetMapping("/active/{id}")
    public Result accountActive(@PathVariable("id") int id){
        log.info("激活用户");
        userService.update(id);

        return Result.success();
    }

    /**
     * 返回验证码图片
     * @return
     */
    @GetMapping("/img")
    public void img(HttpServletResponse response, HttpSession session) throws IOException {
        System.out.println("进行获取验证码信息");
        String text = kaptchaProducer.createText();  //生成随机的文字
        BufferedImage image = kaptchaProducer.createImage(text);//生成随机的图片。

        //我们需要把生成的随机的文字，进行保存，等到登录的时候，拿这个数据来进行校验。
        //保存数据我们在这里使用ThreadLocal保存数据

        //进行保存验证信息的时候，先删除以前保留的验证码信息

        session.removeAttribute("vaild");
        session.setAttribute("vaild",text);

        response.setContentType("image/png");
        OutputStream os = response.getOutputStream();

        ImageIO.write(image, "png", os);
    }

    /**
     * 用户登录的方法
     * @param user
     * @param session
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginVo user, HttpSession session, HttpServletResponse response){
        /**
         * 登录的时候应该把登录用户生成的token放到redis中，
         * 设置一个过期时间，并且在拦截器里面拦截没有携带token的请求。
         * 并且以用户id作为值，存放数据。
         * 拦截器应该不拦截login接口，其它的接口都需要拦截。
         */

        //用户每次登录的时候要先删除原来的用户id,这样才能保证数据是最新的，并且不会重复增加服务器的负担。
        if(session.getAttribute("userId") != null){
            session.removeAttribute("userId");
        }

        System.out.println("用户信息" + user);

        //得到当前的保存到session服务器的验证码
        String vaild = (String) session.getAttribute("vaild");
        System.out.println("服务器端的验证码为：" + vaild);
        UserErrorVO userErrorVO = userService.login(user,vaild);
        log.info("进行登录查询出来的信息为：{}",userErrorVO);

        //保存当前用户的用户id，用来得到用户的详细信息。
        //把数据放入到session中。
        if(userErrorVO.getCode() == 0){
            session.setAttribute("userId",userErrorVO.getUserId());

            /**
             * 用户登录成功之后，要检验当前账户是否已经被登录，如果被登录那么就把之前的账户挤掉。
             */
            String s = stringRedisTemplate.opsForValue().get(userErrorVO.getUserId()+"");
            if(s != null){
                //说明当前用户被登录，那么把前一个账户移除。
                log.info("当前用户已被登录");
                stringRedisTemplate.delete(userErrorVO.getUserId() + "");
            }

            //得到用户信息生成token。
            String token = userErrorVO.getUserId()+ UUIDUtils.getRandomUUID();
            log.info("当前新的登录生成的token为：" + token);
            log.info("旧的生成的token为：" + s);

            //将token保存到redis中。设置过期时间为2小时
            stringRedisTemplate.opsForValue().set(userErrorVO.getUserId()+"",token , 60 * 60 * 2, TimeUnit.SECONDS);

            CookieUtils.setCookie(response, Constans.Cookie_Token, token, 60 * 60 * 24, true);
            CookieUtils.setCookie(response, Constans.Cookie_User, userErrorVO.getUserId()+"", 60 * 60 * 24, true);
        }
        else {
            throw new ServiceException(302,"用户登录出错");
        }
        log.info("用户登录成功");
        return Result.success(userErrorVO);
    }

    /**
     * 得到用户主页的信息。
     * @param session
     * @return
     */
    @LoginAnnotatio
    @GetMapping
    public Result getDetailMessage(@RequestParam("id") Integer id,HttpSession session){
        Integer userId ;
        int temp = 0 ; //辅助变量，用于记录传入的id，是否是当前的用户id。
        Integer currentUserId = (Integer) session.getAttribute("userId");
        if (currentUserId == null){
            currentUserId = Integer.parseInt(ThreadLocalUserId.get());
        }

        if(id == 0 || (int) id == (int) currentUserId){
            //得到用户的用户id，使用用户id查询到用户的信息。
            userId = currentUserId;
            temp = 1;
        }
        else {
            userId = id;
        }
        UserVO userVO = userService.getDetailMessage(userId);
        //得到当前用户的点赞数.
        Integer count = likeService.queryUserLike(userId);
        //得到当前用户的关注数。
        Long attentionNumber = attentionService.getAttention(userId);
        //得到当前用户的粉丝
        Long fansNumber = attentionService.getFans(userId);
        userVO.setLikeCount(count);
        userVO.setAttentionNumber(attentionNumber);
        userVO.setFansNumber(fansNumber);
        //查看当前用户是否关注，如果当前用户是自己的话，返回一个值就是无法关注。
        userVO.setUserCode(0);
        if(temp == 1){
            //当前要查询的用户是自己
            userVO.setUserCode(1);
            userVO.setAttentionMsg("关注TA");
            return Result.success(userVO);
        }

        String attentionMsg = attentionService.getUserIsAttention(userId,currentUserId);
        userVO.setAttentionMsg(attentionMsg);

        return Result.success(userVO);
    }

    /**
     * 上传头像。  并且使用阿里云存储图片。
     * @return
     */
    @LoginAnnotatio
    @PostMapping("/upload")
    public Result upload(@RequestParam("file") MultipartFile image,HttpSession session) throws IOException {
        Integer userid = (Integer)session.getAttribute("userId");
        if (userid == null){
            userid = Integer.parseInt(ThreadLocalUserId.get());
        }
        UserVO userVO = userService.upload(image,userid);
        return Result.success(userVO);
    }

    /**
     * 修改用户密码
     * @param passDTO
     */
    @LoginAnnotatio
    @PutMapping
    public Result updatePass(@RequestBody PassDTO passDTO,HttpSession session){
        Integer userId = (Integer)session.getAttribute("userId");
        if (userId == null){
            userId = Integer.parseInt(ThreadLocalUserId.get());
        }

        UserErrorVO userErrorVO = userService.updatePass(passDTO,userId);
        log.info("码为：" + userErrorVO.getCode());

        return Result.success(userErrorVO);
    }

    @GetMapping("/msg")
    public String msg(){
        String text = "我不喜欢赌博，我喜欢打篮球，但是你妈死了";
        StringBuffer filter = sensitiveWordUtils.filter(text);
        log.info(filter.toString());
        return filter.toString();
    }

    @GetMapping("/currentUser")
    public Result<User> currentUser(HttpServletRequest request,HttpServletResponse response){
//        throw new ServiceException(302,"用户未登录");
        User user = userService.getCurrentUser(request,response);
        return Result.success(user);
    }

}
